﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization.Formatters;
using System.Runtime.Serialization.Formatters.Binary;
using Formatter = System.Runtime.Serialization.Formatters.Binary.BinaryFormatter;
namespace Beetle.Packages
{
    public class BinaryFormatterPackage:HeadSizeOfPackage
    {
        public BinaryFormatterPackage()
        {
        }
        
        public BinaryFormatterPackage(TcpChannel channel)
            : base(channel)
        {
        }
     

        public override object ReadCast(object message)
        {
            return ((MessageAdapter)message).Message;
        }

        public override object WriteCast(object message)
        {
            MessageAdapter adapter = new MessageAdapter();
            adapter.Message = message;
            return adapter;
        }

        public override IMessage MessageRead(BufferReader reader)
        {
            IMessage msg = null;
            object typeTag;
            msg = ReadMessageByType(reader, out typeTag);
            if (msg == null)
                throw NetTcpException.TypeNotFound(typeTag.ToString());
            try
            {
                msg.Load(reader);
            }
            catch (Exception e)
            {
                NetTcpException err = NetTcpException.ObjectLoadError(typeTag.ToString(), e);
                throw err;
            }
            return msg;
        }

        protected override void WriteMessageType(IMessage msg, BufferWriter writer)
        {
            
        }

        protected override IMessage ReadMessageByType(BufferReader reader, out object typeTag)
        {
            typeTag = "Adapter";
            return new MessageAdapter();
        }

        class MessageAdapter:IMessage
        {
            public object Message
            {
                get;
                set;
            }
            public void Load(BufferReader reader)
            {
                ByteArraySegment bas = ByteArraySegment;
                try
                {
                    int count = reader.ReadInt32();
                    reader.Read(count - 4, bas);
                 
                    using (System.IO.MemoryStream stream = new System.IO.MemoryStream(bas.Array, 0, bas.Count))
                    {
                        Formatter formater = new Formatter();
                        Message = formater.Deserialize(stream);
                    }
                }
                catch(Exception e_)
                {
                    throw e_;
                }
                
            }
            public void Save(BufferWriter writer)
            {
                ByteArraySegment bas = ByteArraySegment;
                try
                {
                    
                    using (System.IO.MemoryStream stream = new System.IO.MemoryStream(bas.Array))
                    {
                        Formatter formater = new Formatter();
                        formater.Serialize(stream, Message);
                        bas.SetInfo(0, (int)stream.Position);
                    }
                    writer.Write(bas.Array, 0, bas.Count);
                }
                catch (Exception e_)
                {
                    throw e_;
                }
               
            }

            [ThreadStatic]
            private static ByteArraySegment mByteArraySegment = null;

            public ByteArraySegment ByteArraySegment
            {
                get
                {
                    if (mByteArraySegment == null)
                        mByteArraySegment = new ByteArraySegment(TcpUtils.DataPacketMaxLength);
                    return mByteArraySegment;
                }
            }
        }
    }
}
